package jdiy.sample.action;

import jdiy.sample.interceptor.CheckVipLogin;
import net.jdiy.core.*;
import net.jdiy.core.aop.Before;
import net.jdiy.util.Sec;

import java.util.Date;

//会员相关的Action
public class vip extends JDiyAction {
    App app = App.get();//取得JDiy App上下文
    Dao dao = app.getDao(); //取得默认的数据库操作对象(DataAccessObject)

    //登录和注册的页面（此页面无需相关处理和数据查询，所以直接forward到了jsp页面）
    public void login_and_reg() {
        forward("/WEB-INF/view/vip/login_and_reg.jsp");
    }

    //下面@Before这一行是为main方法添加了一个拦截器，即当会员还没有登录的时候，会被拦截器给拦截掉（进到login_and_reg.jd这个action里面去）
    //JDiy支持三种范围级别的拦截器，一种是像这样写在Action方法上的，它仅对此方法生效；
    //第二种是写在类名上的（例如写在本类的类名即"public class vip extends JDiyAction{"这一行前面），它将对整个Action类中的所有方法生效；
    //第三种是写在jdiy.xml配置文件中的，它针对所有的JDiyAction类生效（即全局的拦截器）。
    @Before({CheckVipLogin.class})
    public void main() throws Exception {

        //获取会话变量，并设置到request请求流中，以便页面输出。
        setAttr("vipName", app.var("vipName"));
        setAttr("vipTypeName", app.var("vipTypeName"));

        forward("/WEB-INF/view/vip/main.jsp");//forward到展现层页面．即将request请求转交页面去输出。
    }

    //会员资料修改的表单Action
    @Before({CheckVipLogin.class})//添加拦截器（仅在登录后才可以访问）
    public void edit() {
        Rs vip = dao.rs(new Args("vip", "id='" + app.var("vipId") + "'"));//获取vipId会话变量，并根据它查询出当前的登录会员
        setAttr("vip", vip);//设置到request流中以便在表单文本框中填充会员信息，让用户修改。
        forward("/WEB-INF/view/vip/edit.jsp"); //forward到展现层页面．即将request请求转交页面去输出。
    }

    //会员点击“退出登录”时，执行此方法，清除会话变量并转到登录页。
    public void do_logout() {
        app.var("vipId, vipName, vipTypeName", null); //清除会话变量（多个会话变量用逗号隔开，第二个参数为null，这样就可以把它们都删除啦～～）
        redirect("login_and_reg.jd");//重定向到login_and_reg的Action去。
    }


    //会员登录时，执行此方法验证用户，并登录
    public void do_login() throws Exception {
        String username = app.get("username");//取提交过来的用户名
        String password = Sec.MD5Encrypt(app.get("password"), 32);//取提交过来的密码并转换成MD5加密字符串（32位大写）

        //注：下面查了两张表，登录成功后要在登录页显示会员所属的会员级别，所以这儿用内连接查询直接把会员的级别查出来了
        //由于JDiy天生具有防SQL注入攻击的能力，所以这儿直接将用户名/密码拼成SQL语句来查询是没有关系的。当然，您如果不放心，也可以用您自己的逻辑做转换处理。
        Rs vip = dao.rs(new Args("vip, viptype",
                "vip.username='" + username + "' AND vip.password='" + password + "' AND vip.viptype=viptype.id",
                "vip.*, viptype.name as vipTypeName"));

        if (vip.isNull()) {
            //从会员表中查不到记录，登录不成功
            setAttr("loginErr", "对不起，用户名或密码不正确！");
            forwardAction("login_and_reg.jd");//登录不成功，仍然forward到login_and_reg这个Action
        } else {
            //登录成功。创建会话变量，并forward到Action。
            this.setVars(vip);//因为会员注册成功后也会直接登录（即有多个地方会设置会话变量），为避免代码重复，所以把创建会话变量的代码单独出来放到一个方法中了。

            redirect("main.jd");//这儿用了redirect(防止登录后点刷新会弹出要重新post的窗口) ,当然您用forwardAction也可以,随便您.
        }
    }

    //会员注册提交处理的Action
    public void do_reg() throws Exception {
        Rs vip = getRs("vip", "vip");//获取从页面POST过来的数据（封包成的Rs对象，注意它是瞬时状态的，数据库中并没有这条记录）
        Rs persist = dao.rs(new Args("vip", "username='" + vip.get("username") + "'"));//从数据库中查会员用户名，用于判断重复.
        if (!persist.isNull()) {
            //下面演示了直接在Action中输出。
            //这儿输出了一个json String,实际应用中会采用相关的JSON工具类来生成json.
            app.getResponse().getWriter().print("{result:'对不起，用户名已经被他人使用，请换个用户名后再试。'}");
            return;
        }

        Rs viptype = dao.rs(new Args("viptype", "order by sort"));//获取第一个会员级别（用于设置注册的用户的默认会员级别）

        vip.set("viptype", viptype.get("id")) //设置刚注册的会员的默认会员级别(对应于后台的会员级别的id)。
                .set("registerdate", new Date())//设置会员的注册日期。
                .set("password", Sec.MD5Encrypt(vip.get("password"), 32));//密码要加密成32位md5大写形式后保存
        //注意上面这三行其实是一条语句哦。Rs类的set方法返回类型是当前的Rs对象本身，因此多个set方法可以连着写。

        dao.save(vip);//将用户注册信息保存到数据库

        vip.set("vipTypeName", viptype.get("name"));//此行要放到dao.save方法后，它仅用于下面的setVars方法中设置会员级别的会话变量，而不能持久化，因为数据库中vip表并没有这个字段。
        this.setVars(vip);//注册成功后，直接将该注册用户的登录状态变为已登录（省去用户注册后还要再登录的麻烦）

        app.getResponse().getWriter().print("{result:'success'}");//示例代码的会员注册是用的ajax/json返回的方式，所以这里直接输出了。
    }

    //会员资料修改提交到的Action
    public void do_edit() throws Exception{
        Rs tmp = getRs("vip", "vip");//获取从页面POST过来的数据（封包成的Rs对象，注意它是瞬时状态的)
        Rs vip = dao.rs(new Args("vip", "id='"+app.var("vipId")+"'"));//根据会话变量vipId查询出当前的会员

        //下面是把提交过来的修改后的数据一个个set到会员记录中去。下面多个set方法是连着写的。
        vip.set("realname", tmp.get("realname"))
                .set("sex", tmp.get("sex"))
                .set("qq", tmp.get("qq"))
                .set("email", tmp.get("email"))
                .set("mt", tmp.get("mt"))
                .set("tel",tmp.get("tel"))
                .set("remark", tmp.get("remark"));

        if(!"".equals(tmp.get("password"))){//有修改密码，则更新密码
            String pwd = Sec.MD5Encrypt(tmp.get("password"),32);//存密码是仍旧要进行md5 32位大写的方式加密
            vip.set("password",pwd);//将密码保存到会员记录
        }
        dao.save(vip);//更新会员信息

        //更新完后设置结果信息并forward到会员资料修改的表单action.
        setAttr("result","修改会员信息操作成功！");
        forwardAction("edit.jd");
    }

    //用于登录成功后设置会话变量，记录登录信息（因为登录成功和注册成功后都会设置会话变量，所以单独出来放在一个方法中。）
    private void setVars(Rs vip) {
        app.var("vipId", vip.get("id"));
        app.var("vipName", vip.get("username"));
        app.var("vipTypeName", vip.get("vipTypeName"));
    }

}
